From 7d2cb3e380c579115177c37079d75d4619f87d0c Mon Sep 17 00:00:00 2001 From: "vh249@arcadians.cl.cam.ac.uk" Date: Fri, 1 Apr 2005 13:20:59 +0000 Subject: [PATCH] bitkeeper revision 1.1236.51.1 (424d4abbioGk0SKwa5bmceZTTxLTTg) big cleanup. better support for refresh. Signed-off-by: Vincent Hanquez --- .../drivers/xen/blkfront/vbd.c | 603 +++++++++--------- 1 file changed, 306 insertions(+), 297 deletions(-) diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c index d7b6aa6aa1..0d335a03ba 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c @@ -31,6 +31,7 @@ #include "block.h" #include +#include /* * For convenience we distinguish between ide, scsi and 'other' (i.e., @@ -42,6 +43,14 @@ #define NUM_SCSI_MAJORS 9 #define NUM_VBD_MAJORS 1 +struct lvdisk +{ + blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */ + blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */ + u16 info; + struct list_head list; +}; + static struct xlbd_type_info xlbd_ide_type = { .partn_shift = 6, .partn_per_major = 2, @@ -66,10 +75,17 @@ static struct xlbd_type_info xlbd_vbd_type = { static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS + NUM_VBD_MAJORS]; +#define XLBD_MAJOR_IDE_START 0 +#define XLBD_MAJOR_SCSI_START (NUM_IDE_MAJORS) +#define XLBD_MAJOR_VBD_START (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) + +#define XLBD_MAJOR_IDE_RANGE XLBD_MAJOR_IDE_START ... XLBD_MAJOR_SCSI_START - 1 +#define XLBD_MAJOR_SCSI_RANGE XLBD_MAJOR_SCSI_START ... XLBD_MAJOR_VBD_START - 1 +#define XLBD_MAJOR_VBD_RANGE XLBD_MAJOR_VBD_START ... XLBD_MAJOR_VBD_START + NUM_VBD_MAJORS - 1 + /* Information about our VBDs. */ #define MAX_VBDS 64 -static int nr_vbds; -static vdisk_t *vbd_info; +struct list_head vbds_list; struct request_queue *xlbd_blk_queue = NULL; @@ -82,388 +98,386 @@ static struct block_device_operations xlvbd_block_fops = .open = blkif_open, .release = blkif_release, .ioctl = blkif_ioctl, -#if 0 - check_media_change: blkif_check, - revalidate: blkif_revalidate, -#endif }; spinlock_t blkif_io_lock = SPIN_LOCK_UNLOCKED; -static int xlvbd_get_vbd_info(vdisk_t *disk_info) +static struct lvdisk * xlvbd_device_alloc(void) +{ + struct lvdisk *ret; + + ret = kmalloc(sizeof(struct lvdisk), GFP_KERNEL); + if ( ret ) { + memset(ret, '\0', 0); + INIT_LIST_HEAD(&ret->list); + } + return ret; +} + +static void xlvbd_device_free(struct lvdisk *disk) +{ + list_del(&disk->list); + kfree(disk); +} + +static vdisk_t * xlvbd_probe(int *ret) { - vdisk_t *buf = (vdisk_t *)__get_free_page(GFP_KERNEL); - blkif_request_t req; blkif_response_t rsp; - int nr; + blkif_request_t req; + vdisk_t *disk_info = NULL; + unsigned long buf; + int nr; + + buf = __get_free_page(GFP_KERNEL); + if ( !buf ) + goto out; memset(&req, 0, sizeof(req)); - req.operation = BLKIF_OP_PROBE; + req.operation = BLKIF_OP_PROBE; req.nr_segments = 1; req.frame_and_sects[0] = virt_to_machine(buf) | 7; blkif_control_send(&req, &rsp); - - if ( rsp.status <= 0 ) - { + if ( rsp.status <= 0 ) { printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status); - return -1; + goto out; } - - if ( (nr = rsp.status) > MAX_VBDS ) + nr = rsp.status; + if ( nr > MAX_VBDS ) nr = MAX_VBDS; - memcpy(disk_info, buf, nr * sizeof(vdisk_t)); - - free_page((unsigned long)buf); - return nr; + disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL); + if ( disk_info ) + memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t)); + if ( ret ) + *ret = nr; +out: + free_page(buf); + return disk_info; } -static struct xlbd_major_info *xlbd_get_major_info(int xd_device, int *minor) +static struct xlbd_major_info *xlbd_alloc_major_info(int major, int minor, int index) { - int mi_idx, new_major; - int xd_major = MAJOR_XEN(xd_device); - int xd_minor = MINOR_XEN(xd_device); - - *minor = xd_minor; - - switch (xd_major) { - case IDE0_MAJOR: mi_idx = 0; new_major = IDE0_MAJOR; break; - case IDE1_MAJOR: mi_idx = 1; new_major = IDE1_MAJOR; break; - case IDE2_MAJOR: mi_idx = 2; new_major = IDE2_MAJOR; break; - case IDE3_MAJOR: mi_idx = 3; new_major = IDE3_MAJOR; break; - case IDE4_MAJOR: mi_idx = 4; new_major = IDE4_MAJOR; break; - case IDE5_MAJOR: mi_idx = 5; new_major = IDE5_MAJOR; break; - case IDE6_MAJOR: mi_idx = 6; new_major = IDE6_MAJOR; break; - case IDE7_MAJOR: mi_idx = 7; new_major = IDE7_MAJOR; break; - case IDE8_MAJOR: mi_idx = 8; new_major = IDE8_MAJOR; break; - case IDE9_MAJOR: mi_idx = 9; new_major = IDE9_MAJOR; break; - case SCSI_DISK0_MAJOR: mi_idx = 10; new_major = SCSI_DISK0_MAJOR; break; - case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: - mi_idx = 11 + xd_major - SCSI_DISK1_MAJOR; - new_major = SCSI_DISK1_MAJOR + xd_major - SCSI_DISK1_MAJOR; - break; - case SCSI_CDROM_MAJOR: mi_idx = 18; new_major = SCSI_CDROM_MAJOR; break; - default: mi_idx = 19; new_major = 0;/* XXXcl notyet */ break; - } + struct xlbd_major_info *ptr; - if (major_info[mi_idx]) - return major_info[mi_idx]; - - major_info[mi_idx] = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); - if (major_info[mi_idx] == NULL) + ptr = kmalloc(sizeof(struct xlbd_major_info), GFP_KERNEL); + if ( !ptr ) return NULL; - memset(major_info[mi_idx], 0, sizeof(struct xlbd_major_info)); + memset(ptr, 0, sizeof(struct xlbd_major_info)); + + ptr->major = major; - switch (mi_idx) { - case 0 ... (NUM_IDE_MAJORS - 1): - major_info[mi_idx]->type = &xlbd_ide_type; - major_info[mi_idx]->index = mi_idx; + switch (index) { + case XLBD_MAJOR_IDE_RANGE: + ptr->type = &xlbd_ide_type; + ptr->index = index - XLBD_MAJOR_IDE_START; break; - case NUM_IDE_MAJORS ... (NUM_IDE_MAJORS + NUM_SCSI_MAJORS - 1): - major_info[mi_idx]->type = &xlbd_scsi_type; - major_info[mi_idx]->index = mi_idx - NUM_IDE_MAJORS; + case XLBD_MAJOR_SCSI_RANGE: + ptr->type = &xlbd_scsi_type; + ptr->index = index - XLBD_MAJOR_SCSI_START; break; - case (NUM_IDE_MAJORS + NUM_SCSI_MAJORS) ... - (NUM_IDE_MAJORS + NUM_SCSI_MAJORS + NUM_VBD_MAJORS - 1): - major_info[mi_idx]->type = &xlbd_vbd_type; - major_info[mi_idx]->index = mi_idx - - (NUM_IDE_MAJORS + NUM_SCSI_MAJORS); + case XLBD_MAJOR_VBD_RANGE: + ptr->type = &xlbd_vbd_type; + ptr->index = index - XLBD_MAJOR_VBD_START; break; } - major_info[mi_idx]->major = new_major; - - if (register_blkdev(major_info[mi_idx]->major, major_info[mi_idx]->type->devname)) { + + if ( register_blkdev(ptr->major, ptr->type->devname) ) { printk(KERN_ALERT "XL VBD: can't get major %d with name %s\n", - major_info[mi_idx]->major, major_info[mi_idx]->type->devname); - goto out; + ptr->major, ptr->type->devname); + kfree(ptr); + return NULL; + } + + devfs_mk_dir(ptr->type->devname); + major_info[index] = ptr; + return ptr; +} + +static struct xlbd_major_info *xlbd_get_major_info(int device) +{ + int major, minor, index; + + major = MAJOR_XEN(device); + minor = MINOR_XEN(device); + + switch (major) { + case IDE0_MAJOR: index = 0; break; + case IDE1_MAJOR: index = 1; break; + case IDE2_MAJOR: index = 2; break; + case IDE3_MAJOR: index = 3; break; + case IDE4_MAJOR: index = 4; break; + case IDE5_MAJOR: index = 5; break; + case IDE6_MAJOR: index = 6; break; + case IDE7_MAJOR: index = 7; break; + case IDE8_MAJOR: index = 8; break; + case IDE9_MAJOR: index = 9; break; + case SCSI_DISK0_MAJOR: index = 10; break; + case SCSI_DISK1_MAJOR ... SCSI_DISK7_MAJOR: + index = 11 + major - SCSI_DISK1_MAJOR; + break; + case SCSI_CDROM_MAJOR: index = 18; break; + default: index = 19; break; } - devfs_mk_dir(major_info[mi_idx]->type->devname); + return major_info[index] + ? major_info[index] + : xlbd_alloc_major_info(major, minor, index); +} - return major_info[mi_idx]; +static int xlvbd_blk_queue_alloc(struct xlbd_type_info *type) +{ + xlbd_blk_queue = blk_init_queue(do_blkif_request, &blkif_io_lock); + if ( !xlbd_blk_queue ) + return -1; - out: - kfree(major_info[mi_idx]); - major_info[mi_idx] = NULL; - return NULL; + elevator_init(xlbd_blk_queue, "noop"); + + /* + * Turn off barking 'headactive' mode. We dequeue + * buffer heads as soon as we pass them to back-end + * driver. + */ + blk_queue_headactive(xlbd_blk_queue, 0); + + /* Hard sector size and max sectors impersonate the equiv. hardware. */ + blk_queue_hardsect_size(xlbd_blk_queue, 512); + blk_queue_max_sectors(xlbd_blk_queue, 512); + + /* Each segment in a request is up to an aligned page in size. */ + blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1); + blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE); + + /* Ensure a merged request will fit in a single I/O ring slot. */ + blk_queue_max_phys_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); + blk_queue_max_hw_segments(xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); + + /* Make sure buffer addresses are sector-aligned. */ + blk_queue_dma_alignment(xlbd_blk_queue, 511); + return 0; } -static struct gendisk *xlvbd_get_gendisk(struct xlbd_major_info *mi, - int xd_minor, vdisk_t *xd) +struct gendisk *xlvbd_alloc_gendisk(struct xlbd_major_info *mi, int minor, + vdisk_t *disk) { struct gendisk *gd; struct xlbd_disk_info *di; - int device, partno; - - device = MKDEV(mi->major, xd_minor); - gd = get_gendisk(device, &partno); - if ( gd != NULL ) - return gd; + int nb_minors; di = kmalloc(sizeof(struct xlbd_disk_info), GFP_KERNEL); - if ( di == NULL ) - return NULL; + if ( !di ) + goto out; di->mi = mi; - di->xd_device = xd->device; + di->xd_device = disk->device; - /* Construct an appropriate gendisk structure. */ - gd = alloc_disk(1); - if ( gd == NULL ) + nb_minors = ((minor & ((1 << mi->type->partn_shift) - 1)) == 0) + ? mi->type->partn_per_major + : 1; + + gd = alloc_disk(nb_minors); + if ( !gd ) goto out; + if ( nb_minors > 1 ) + sprintf(gd->disk_name, "%s%c", mi->type->diskname, + 'a' + mi->index * mi->type->partn_per_major + + (minor >> mi->type->partn_shift)); + else + sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, + 'a' + mi->index * mi->type->partn_per_major + + (minor >> mi->type->partn_shift), + minor & ((1 << mi->type->partn_shift) - 1)); + gd->major = mi->major; - gd->first_minor = xd_minor; + gd->first_minor = minor; gd->fops = &xlvbd_block_fops; gd->private_data = di; - sprintf(gd->disk_name, "%s%c%d", mi->type->diskname, - 'a' + mi->index * mi->type->partn_per_major + - (xd_minor >> mi->type->partn_shift), - xd_minor & ((1 << mi->type->partn_shift) - 1)); - - set_capacity(gd, xd->capacity); - - if ( xlbd_blk_queue == NULL ) - { - xlbd_blk_queue = blk_init_queue(do_blkif_request, - &blkif_io_lock); - if ( xlbd_blk_queue == NULL ) - goto out; - elevator_init(xlbd_blk_queue, "noop"); - - /* - * Turn off barking 'headactive' mode. We dequeue buffer heads as soon - * as we pass them to back-end driver. - */ - blk_queue_headactive(xlbd_blk_queue, 0); - - blk_queue_hardsect_size(xlbd_blk_queue, 512); - blk_queue_max_sectors(xlbd_blk_queue, 512); - - /* Each segment in a request is up to an aligned page in size. */ - blk_queue_segment_boundary(xlbd_blk_queue, PAGE_SIZE - 1); - blk_queue_max_segment_size(xlbd_blk_queue, PAGE_SIZE); - - /* Ensure a merged request will fit in a single I/O ring slot. */ - blk_queue_max_phys_segments( - xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); - blk_queue_max_hw_segments( - xlbd_blk_queue, BLKIF_MAX_SEGMENTS_PER_REQUEST); - - /* Make sure buffer addresses are sector-aligned. */ - blk_queue_dma_alignment(xlbd_blk_queue, 511); - } - gd->queue = xlbd_blk_queue; + set_capacity(gd, disk->capacity); - add_disk(gd); + if ( !xlbd_blk_queue ) + if ( xlvbd_blk_queue_alloc(mi->type) ) + goto out_gendisk; + gd->queue = xlbd_blk_queue; + add_disk(gd); return gd; - - out: - if ( gd != NULL ) - del_gendisk(gd); +out_gendisk: + printk(KERN_ALERT "error gendisk\n"); + del_gendisk(gd); +out: + printk(KERN_ALERT "error out\n"); kfree(di); return NULL; } -/* - * xlvbd_init_device - initialise a VBD device - * @disk: a vdisk_t describing the VBD - * - * Takes a vdisk_t * that describes a VBD the domain has access to. - * Performs appropriate initialisation and registration of the device. - * - * Care needs to be taken when making re-entrant calls to ensure that - * corruption does not occur. Also, devices that are in use should not have - * their details updated. This is the caller's responsibility. - */ -static int xlvbd_init_device(vdisk_t *xd) +static int xlvbd_device_add(struct list_head *list, vdisk_t *disk) { + struct lvdisk *new; + int minor; + dev_t device; struct block_device *bd; struct gendisk *gd; struct xlbd_major_info *mi; - int device; - int minor; - int err = -ENOMEM; - - mi = xlbd_get_major_info(xd->device, &minor); - if (mi == NULL) + mi = xlbd_get_major_info(disk->device); + if ( !mi ) return -EPERM; + new = xlvbd_device_alloc(); + if ( !new ) + return -1; + new->capacity = disk->capacity; + new->device = disk->device; + new->info = disk->info; + + minor = MINOR_XEN(disk->device); device = MKDEV(mi->major, minor); - - if ((bd = bdget(device)) == NULL) - return -EPERM; - - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ + + bd = bdget(device); + if ( !bd ) + goto out; + down(&bd->bd_sem); - gd = xlvbd_get_gendisk(mi, minor, xd); - if (gd == NULL) { - err = -EPERM; - goto out; - } + gd = xlvbd_alloc_gendisk(mi, minor, disk); + if ( !gd ) + goto out_bd; - if (VDISK_READONLY(xd->info)) - set_disk_ro(gd, 1); + if ( VDISK_READONLY(disk->info) ) + set_disk_ro(gd, 1); - /* Some final fix-ups depending on the device type */ - switch (VDISK_TYPE(xd->info)) { + switch (VDISK_TYPE(disk->info)) { case VDISK_TYPE_CDROM: - gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; - /* FALLTHROUGH */ + gd->flags |= GENHD_FL_REMOVABLE | GENHD_FL_CD; + break; case VDISK_TYPE_FLOPPY: case VDISK_TYPE_TAPE: - gd->flags |= GENHD_FL_REMOVABLE; - break; - + gd->flags |= GENHD_FL_REMOVABLE; + break; case VDISK_TYPE_DISK: - break; - + break; default: - printk(KERN_ALERT "XenLinux: unknown device type %d\n", - VDISK_TYPE(xd->info)); - break; - } + printk(KERN_ALERT "XenLinux: unknown device type %d\n", + VDISK_TYPE(disk->info)); + break; + } - err = 0; - out: + list_add(&new->list, list); +out_bd: up(&bd->bd_sem); - bdput(bd); - return err; + bdput(bd); +out: + return 0; } -/* - * xlvbd_remove_device - remove a device node if possible - * @device: numeric device ID - * - * Updates the gendisk structure and invalidates devices. - * - * This is OK for now but in future, should perhaps consider where this should - * deallocate gendisks / unregister devices. - */ -static int xlvbd_remove_device(int dev16) +static int xlvbd_device_del(struct lvdisk *disk) { - int i, rc = 0; - struct gendisk *gd; + dev_t device; struct block_device *bd; + struct gendisk *gd; struct xlbd_disk_info *di; - dev_t device = MKDEV(MAJOR_XEN(dev16), MINOR_XEN(dev16)); + int ret = 0, unused; + + device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device)); bd = bdget(device); - if (!bd) + if ( !bd ) return -1; - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ down(&bd->bd_sem); - gd = get_gendisk(device, &i); - BUG_ON(gd == NULL); - di = (struct xlbd_disk_info *) gd->private_data; - BUG_ON(di == NULL); + gd = get_gendisk(device, &unused); + di = gd->private_data; - if ( di->mi->usage != 0 ) - { - printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device); - rc = -1; + if ( di->mi->usage != 0 ) { + printk(KERN_ALERT "VBD removal failed: used [dev=%x]\n", device); + ret = -1; goto out; } - /* The VBD is mapped to an entire unit. */ - - invalidate_partition(gd, 0); - set_capacity(gd, 0); + del_gendisk(gd); + xlvbd_device_free(disk); out: up(&bd->bd_sem); bdput(bd); - return rc; + return ret; } -/* - * xlvbd_update_vbds - reprobes the VBD status and performs updates driver - * state. The VBDs need to be updated in this way when the domain is - * initialised and also each time we receive an XLBLK_UPDATE event. - */ -void xlvbd_update_vbds(void) +static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk) { - int i, j, k, old_nr, new_nr; - vdisk_t *old_info, *new_info, *merged_info; + dev_t device; + struct block_device *bd; + struct gendisk *gd; + int unused; - old_info = vbd_info; - old_nr = nr_vbds; + if ( ldisk->capacity == disk->capacity && ldisk->info == disk->info ) + return 0; - new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL); - if (!new_info) - return; + device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device)); - if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 ) - goto out; + bd = bdget(device); + if ( !bd ) + return -1; - /* - * Final list maximum size is old list + new list. This occurs only when - * old list and new list do not overlap at all, and we cannot yet destroy - * VBDs in the old list because the usage counts are busy. - */ - merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL); - if (!merged_info) - goto out; + down(&bd->bd_sem); - /* @i tracks old list; @j tracks new list; @k tracks merged list. */ - i = j = k = 0; + gd = get_gendisk(device, &unused); + set_capacity(gd, disk->capacity); + ldisk->capacity = disk->capacity; - while ( (i < old_nr) && (j < new_nr) ) - { - if ( old_info[i].device < new_info[j].device ) - { - if ( xlvbd_remove_device(old_info[i].device) != 0 ) - memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t)); - i++; - } - else if ( old_info[i].device > new_info[j].device ) - { - if ( xlvbd_init_device(&new_info[j]) == 0 ) - memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t)); - j++; - } - else - { - if ( ((old_info[i].capacity == new_info[j].capacity) && - (old_info[i].info == new_info[j].info)) || - (xlvbd_remove_device(old_info[i].device) != 0) ) - memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t)); - else if ( xlvbd_init_device(&new_info[j]) == 0 ) - memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t)); - i++; j++; - } - } + up(&bd->bd_sem); + bdput(bd); - for ( ; i < old_nr; i++ ) - { - if ( xlvbd_remove_device(old_info[i].device) != 0 ) - memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t)); - } + return 0; +} - for ( ; j < new_nr; j++ ) - { - if ( xlvbd_init_device(&new_info[j]) == 0 ) - memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t)); +void xlvbd_refresh(void) +{ + vdisk_t *newdisks; + struct list_head *tmp, *tmp2; + struct lvdisk *disk; + int i, nr; + + newdisks = xlvbd_probe(&nr); + if ( !newdisks ) { + printk(KERN_ALERT "failed to probe\n"); + return; } + + i = 0; + list_for_each_safe(tmp, tmp2, &vbds_list) { + disk = list_entry(tmp, struct lvdisk, list); + + for (i = 0; i < nr; i++) { + if ( !newdisks[i].device ) + continue; + if ( disk->device == newdisks[i].device ) { + xlvbd_device_update(disk, &newdisks[i]); + newdisks[i].device = 0; + break; + } + } + if ( i == nr ) { + xlvbd_device_del(disk); + newdisks[i].device = 0; + } + } + for (i = 0; i < nr; i++) + if ( newdisks[i].device ) + xlvbd_device_add(&vbds_list, &newdisks[i]); + kfree(newdisks); +} - vbd_info = merged_info; - nr_vbds = k; - - kfree(old_info); -out: - kfree(new_info); +/* + * xlvbd_update_vbds - reprobes the VBD status and performs updates driver + * state. The VBDs need to be updated in this way when the domain is + * initialised and also each time we receive an XLBLK_UPDATE event. + */ +void xlvbd_update_vbds(void) +{ + xlvbd_refresh(); } /* @@ -477,26 +491,21 @@ out: */ int xlvbd_init(void) { - int i; - - memset(major_info, 0, sizeof(major_info)); + int i, nr; + vdisk_t *disks; - vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL); - if (vbd_info == NULL) { - printk(KERN_ALERT "Failed to allocate memory for disk info.\n"); - nr_vbds = 0; - return 0; - } + INIT_LIST_HEAD(&vbds_list); - nr_vbds = xlvbd_get_vbd_info(vbd_info); - if (nr_vbds < 0) { - kfree(vbd_info); - vbd_info = NULL; - nr_vbds = 0; - } else { - for (i = 0; i < nr_vbds; i++) - xlvbd_init_device(&vbd_info[i]); + memset(major_info, 0, sizeof(major_info)); + + disks = xlvbd_probe(&nr); + if ( !disks ) { + printk(KERN_ALERT "failed to probe\n"); + return -1; } + for (i = 0; i < nr; i++) + xlvbd_device_add(&vbds_list, &disks[i]); + kfree(disks); return 0; } -- 2.30.2